import java.util.Comparator;
import java.util.Objects;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User:张熳
 * Date:2025-11-25
 * Time:17:07
 */
//Java对象的比较
/*
    equals：返回值类型是布尔类型，判断的是两个对象是不是相同的。  Java中引用类型的变量不能直接按照 > 或者 < 方式进行比较。 那为什么==可以比较？
因为：对于用户实现自定义类型，都默认继承自Object类，而Object类中提供了equal方法，而==默认情况下调用的就是equal方法，但是该方法的比较规则是：
没有比较引用变量引用对象的内容，而是直接比较引用变量的地址。
    Comparable：返回值类型是整型，它的作用是比较两个对象的大小
    Comparator：返回值类型是整型，它也可以比较大小
    上述两个接口类型的区别在于：Comparable一般在当前类中使用，Comparator是脱离当前类来使用的
*/
class Card {
    public String suit;
    public int rank;

    public Card(String suit,int rank) {
        this.suit = suit;
        this.rank = rank;
    }

    @Override
    public boolean equals(Object o) {
        //自己和自己比较
        if (this == o) return true;
        //o如果是null对象，或者o不是Card的子类
        if (o == null || getClass() != o.getClass()) return false;
        //注意基本类型可以直接比较，但引用类型最好调用其equal方法
        Card card = (Card) o;
        return rank == card.rank && Objects.equals(suit, card.suit);
    }

    @Override
    public int hashCode() {
        return Objects.hash(suit, rank);
    }

    @Override
    public String toString() {
        return "Card{" +
                "suit='" + suit + '\'' +
                ", rank=" + rank +
                '}';
    }
}

class Card1 implements Comparable<Card1> {
    public String suit;
    public int rank;

    public Card1(String suit,int rank) {
        this.suit = suit;
        this.rank = rank;
    }

    @Override
    public int compareTo(Card1 o) {
        return this.rank - o.rank;
    }
}

class SuitComparator implements Comparator<Card1> {
    @Override
    public int compare(Card1 o1, Card1 o2) {
        return o1.suit.compareTo(o2.suit);
    }
}

public class Test {
    public static void main(String[] args) {
        //为了解决main2中提到的问题，应该使用Comparator接口，可以自由使用rank或者suit进行比较：创建一个类专门使用rank比较，创建另一个类专门
        //使用suit比较
        Card1 card1 = new Card1("hongtao",15);
        Card1 card2 = new Card1("heitao",5);
        SuitComparator suitComparator = new SuitComparator();
        if (suitComparator.compare(card1,card2) > 0) {
            System.out.println("card1 > card2");
        }else {
            System.out.println("card1 <= card2");
        }

        //三种方式对比
        /*
        Object.equals:因为所有类都是继承自 Object 的，所以直接覆写即可，不过只能比较相等与否
        Comparable.compareTo:需要手动实现接口，侵入性比较强，但一旦实现，每次用该类都有顺序，属于内部顺序
        Comparator.compare:需要实现一个比较器对象，对待比较类的侵入性弱，但对算法代码实现侵入性强
         */
    }
    public static void main2(String[] args) {
        Card1 card1 = new Card1("hongtao",15);
        Card1 card2 = new Card1("heitao",5);
        //使用Comparable接口，以下是根据rank比较的，如果想要改成使用suit比较，那么直接修改compareTo方法是不好的，因为以下的代码就是根据rank
        //比较的情况下写的，改成根据suit比较后，以下的代码也要跟着修改(根据rank比较和根据suit比较的结果可能会不同，例如根据suit比较如果大于0的
        // 情况可能是 card1<card2)，可谓是牵一发而动全身
        if (card1.compareTo(card2) > 0) {
            System.out.println("card1 > card2");
        }else {
            System.out.println("card1 <= card2");
        }
    }
    public static void main1(String[] args) {
        Card card1 = new Card("hongtao",5);
        Card card2 = new Card("hongtao",5);

        System.out.println(card1 == card2);//输出结果是false，== 只能比较引用变量的地址，而不能比较引用变量引用的内容
        System.out.println(card1.equals(card2));//使用equals输出的也是false，==默认情况下调用的就是equal方法
        //解决方法就是重写equals方法,重写完equals之后，上述的结果就会输出true
        //重写equal的方式虽然可以比较，但缺陷是：equal只能按照相等进行比较，不能按照大于、小于的方式进行比较，想要比较大小，有两种方法：
        //1.基于Comparable接口类的比较：对用用户自定义类型，如果要想按照大小与方式进行比较时：在定义类时，实现Comparable接口即可，然后在类
        //中重写compareTo方法。Comparable是java.lang中的接口类，可以直接使用。
        //2.基于比较器比较：用户自定义比较器类，实现Comparator接口，覆写Comparator中的compare方法。Comparator是java.util 包
        //中的泛型接口类，使用时必须导入对应的包。
    }
}
